package cn.tedu.mall.order.listener;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.front.service.IFrontSkuService;
import cn.tedu.mall.order.mapper.OrderItemMapper;
import cn.tedu.mall.order.mapper.OrderMapper;
import cn.tedu.mall.pojo.order.dto.OrderAddCondition;
import cn.tedu.mall.pojo.order.dto.OrderAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderItemAddDTO;
import cn.tedu.mall.pojo.order.model.OmsOrder;
import cn.tedu.mall.pojo.order.model.OmsOrderItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 这个实现类,实现了OrderAddDTO的事务监听逻辑
 */
@Component
@Slf4j
public class OrderAddListenerLocalAddImpl implements OrderAddListenerExecutorInter, InitializingBean {
    @DubboReference
    private IFrontSkuService skuService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired//操作表格 oms_order
    private OrderMapper orderMapper;

    @Autowired//操作表格oms_order_item
    private OrderItemMapper orderItemMapper;

    @Override
    public RocketMQLocalTransactionState execute(OrderAddCondition orderAddCondition) {
        //OBJECT先转化
        OrderAddDTO orderAddDTO = (OrderAddDTO) orderAddCondition;
        //减库存 远程dubbo skuId quantity
        try {
            skuService.reduceSkusCounts
                    (orderAddDTO.getOrderItems(), orderAddDTO.getSn());
        } catch (CoolSharkServiceException e) {
            //减库存失败
            log.error("业务异常:{}", e.getMessage());
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        //不建议手写insert语句,看看源码中新增订单
        //oms_order 订单表格,oms_order_item
        //准备一个持久层新增订单的OmsOrder entity对象
        OmsOrder omsOrder = new OmsOrder();
        //封装数据,先把orderAddDTO有的数据转过来
        BeanUtils.copyProperties(orderAddDTO, omsOrder);
        //业务方还需要将omsOrder中缺少的字段补齐
        replenishOrder(omsOrder);
        try {
            orderMapper.insertOrder(omsOrder);
        } catch (Exception e) {
            log.error("业务异常:{}", e.getMessage());
            return RocketMQLocalTransactionState.UNKNOWN;
        }
        //新增订单,还要新增订单商品
        List<OmsOrderItem> omsOrderItemList = new ArrayList<>();
        List<OrderItemAddDTO> orderItems = orderAddDTO.getOrderItems();
        for (OrderItemAddDTO orderItem : orderItems) {
            OmsOrderItem omsOrderItem = new OmsOrderItem();
            //转化
            BeanUtils.copyProperties(orderItem, omsOrderItem);
            //列表集合中添加entity
            omsOrderItemList.add(omsOrderItem);
            //写入一个orderId
            omsOrderItem.setOrderId(omsOrder.getId());
        }
        try {
            orderItemMapper.insertOrderItems(omsOrderItemList);
        } catch (Exception e) {
            log.error("业务异常:{}", e.getMessage());
            return RocketMQLocalTransactionState.UNKNOWN;
        }

        //订单新增时候,有超时未支付的检查 15分钟30分钟 2/3这个级别 2秒 10秒
        //发送一个延迟队列,在消息中添加一个延迟级别的头 默认0 不延迟
        Message<String> message =
                MessageBuilder.withPayload(orderAddDTO.getSn()).build();
        SendResult sendResult = rocketMQTemplate.syncSend(
                "csmall-order-delay-topic", message, 5000, 3);
        if (sendResult.getSendStatus().toString().equals("SEND_OK")) {
            return RocketMQLocalTransactionState.COMMIT;
        } else {
            log.error("延迟消息发送失败,记录日志,手动,人工处理");
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }

    private void replenishOrder(OmsOrder omsOrder) {
        //state 订单状态 默认 未支付0
        //已支付,已发货,待收货,已收货,已关闭1,已取消,已退单
        omsOrder.setState(0);
        //时间字段 创建时间 修改时间 订单新增时间
        LocalDateTime now = LocalDateTime.now();
        omsOrder.setGmtOrder(now);
        omsOrder.setGmtModified(now);
        omsOrder.setGmtCreate(now);
        //UNDO 添加加钱,并且追加校验规则
    }

    /**
     * 所有spring中bean对象,在声明创建之后,所有的依赖关系完成注入
     * 都会调用这个方法afterPropertiesSet
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        OrderAddListenerRegister.registe(
                OrderAddDTO.class.getName(), this);
    }
}
